package info.mpem.android.translate;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.TabActivity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.BasicHttpContext;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.zip.GZIPInputStream;

public class TranslateActivity extends TabActivity {

    private static final String UTF_8 = "UTF-8";
    private static final String ISO_8859_1 = "ISO-8859-1";
    private List<Language> supportedLanguages = new ArrayList<Language>();
    private static final String url = "https://ajax.googleapis.com/ajax/services/language/translate?key=AIzaSyDFis9UrYGxgNph314zCj3Vpkyaj3p-r9E&v=1.0&q={0}&langpair={1}%7C{2}&langpair={1}%7C{3}";
    private final String[] translate = new String[]{Locale.ENGLISH.getLanguage(), Locale.GERMAN.getLanguage(), Locale.FRENCH.getLanguage()};
    private static final int MAX_NO_LANGUAGES = 3;
    private Menu menu;
    private TabHost mTabHost;
    private SharedPreferences mPrefs;

    private Handler mHandler = new Handler();


    private static final int[] flags = new int[]{-1
            , R.drawable.albanian
            , -1
            , -1
            , R.drawable.belarusian
            , R.drawable.bulgarian
            , -1
            , R.drawable.chinese
            , R.drawable.chinese
            , R.drawable.croatian
            , R.drawable.czech
            , R.drawable.danish
            , R.drawable.dutch
            , R.drawable.english
            , R.drawable.estonian
            , -1
            , R.drawable.finnish
            , R.drawable.french
            , -1
            , R.drawable.german
            , R.drawable.greek
            , R.drawable.haitian
            , R.drawable.hebrew
            , R.drawable.hindi
            , R.drawable.hungarian
            , R.drawable.icelandic
            , R.drawable.indonesian
            , R.drawable.irish
            , R.drawable.italian
            , R.drawable.japanese
            , R.drawable.latvian
            , -1
            , R.drawable.macedonian
            , R.drawable.malay
            , R.drawable.maltese
            , R.drawable.norwegian
            , R.drawable.persian
            , R.drawable.polish
            , R.drawable.portuguese
            , R.drawable.romanian
            , R.drawable.russian
            , R.drawable.serbian
            , R.drawable.slovak
            , R.drawable.slovenian
            , R.drawable.spanish
            , -1
            , R.drawable.swedish
            , R.drawable.thai
            , R.drawable.turkish
            , R.drawable.ukrainian
            , R.drawable.vietnamese
            , -1
            , -1};


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final String[] countryCodes = getResources().getStringArray(R.array.country_codes);
        final String[] languages = getResources().getStringArray(R.array.languages_array);

        mPrefs = getSharedPreferences("translate", MODE_PRIVATE);

        final String defaultLanguage = isSupported(getResources().getConfiguration().locale.getLanguage(), countryCodes);
        translate[0] = mPrefs.getString("language_1", defaultLanguage);
        translate[1] = mPrefs.getString("language_2", Locale.GERMAN.getLanguage().equalsIgnoreCase(defaultLanguage) ? Locale.ENGLISH.getLanguage() : Locale.GERMAN.getLanguage());
        translate[2] = mPrefs.getString("language_3",Locale.FRENCH.getLanguage().equalsIgnoreCase(defaultLanguage) ? Locale.ENGLISH.getLanguage() : Locale.FRENCH.getLanguage());

        mTabHost = getTabHost();


        loadLanguages(languages, countryCodes);
        final android.widget.ListView listView = (android.widget.ListView) findViewById(R.id.list_countries);
        final ArrayAdapter<Language> languageArrayAdapter = new ArrayAdapter<Language>(getBaseContext(), R.layout.list_item, supportedLanguages);
        listView.setAdapter(languageArrayAdapter);
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        listView.setClickable(true);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                final long[] checkItemIds = listView.getCheckItemIds();
                if (((CheckBox) view).isChecked()) {
                    listView.clearChoices();
                    for (long index : checkItemIds) {
                        if (index != position) listView.setItemChecked((int) index, true);
                    }
                } else {
                    listView.setItemChecked(position, true);
                }
            }
        });


        for (int i = 0; i < translate.length; i++) {
            for (int j = 0; j < countryCodes.length; j++) {
                if (countryCodes[j].equalsIgnoreCase(translate[i])) {
                    listView.setItemChecked(j, true);
                    switch (i) {
                        case 0:
                            mTabHost.addTab(mTabHost.newTabSpec("tab_test1").setIndicator(languages[j], flags[j] == -1 ? null : getResources().getDrawable(flags[j])).setContent(R.id.language_1));
                            break;
                        case 1:
                            mTabHost.addTab(mTabHost.newTabSpec("tab_test2").setIndicator(languages[j], flags[j] == -1 ? null : getResources().getDrawable(flags[j])).setContent(R.id.language_2));
                            break;
                        case 2:
                            mTabHost.addTab(mTabHost.newTabSpec("tab_test3").setIndicator(languages[j], flags[j] == -1 ? null : getResources().getDrawable(flags[j])).setContent(R.id.language_3));
                            break;
                    }
                }
            }
        }
        mTabHost.addTab(mTabHost.newTabSpec("tab_test4").setIndicator("", getResources().getDrawable(R.drawable.ic_menu_manage)).setContent(R.id.layout_languages));
        mTabHost.setCurrentTab(0);

        ((Button) findViewById(R.id.save)).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                final long[] checkItemIds = listView.getCheckItemIds();
                if (checkItemIds.length > MAX_NO_LANGUAGES) {
                    new AlertDialog.Builder(view.getContext())
                            .setTitle(getResources().getString(R.string.setting_too_many_languages) + checkItemIds.length + "\n " + getResources().getString(R.string.setting_select_3_languages))
                            .setPositiveButton(getString(R.string.translation_button_ok), null).show();
                    return;
                }
                for (int i = 0; i < translate.length; i++) {
                    translate[i] = supportedLanguages.get((int) listView.getCheckItemIds()[i]).getCountryCode();
                }
                updateLanguageInputs();
                mTabHost.setCurrentTab(0);

            }
        });
        ((Button) findViewById(R.id.translate_1)).setOnClickListener(new TranslateOnClickListener(0, (EditText) findViewById(R.id.input_1)));
        ((Button) findViewById(R.id.translate_2)).setOnClickListener(new TranslateOnClickListener(1, (EditText) findViewById(R.id.input_2)));
        ((Button) findViewById(R.id.translate_3)).setOnClickListener(new TranslateOnClickListener(2, (EditText) findViewById(R.id.input_3)));

    }

    private String isSupported(String language, String[] countryCodes) {
        for (String code : countryCodes) {
            if (code.equalsIgnoreCase(language)) return language;
        }
        return Locale.ENGLISH.getLanguage();
    }

    private class TranslateOnClickListener implements OnClickListener {
        private int fromIndex = 0;
        private EditText input;

        public TranslateOnClickListener(int languageIndex, EditText input) {
            this.fromIndex = languageIndex;
            this.input = input;
        }

        private class TranslateRunnable implements Runnable {

            private ProgressDialog progressDialog;

            private TranslateRunnable(ProgressDialog progressDialog) {
                this.progressDialog = progressDialog;
            }


            public void run() {
                String errorMessage = null;
                try {
                    String inputText = Uri.encode(convertFromEncodingToEncoding(input.getEditableText().toString(), Charset.defaultCharset().name(), UTF_8));
                    Object[] values = new Object[4];
                    values[0] = inputText;
                    values[1] = translate[fromIndex];
                    int j = 2;

                    for (int toIndex = 0; toIndex < translate.length; toIndex++) {
                        if (toIndex == fromIndex) continue;
                        values[j++] = translate[toIndex];
                    }

                    final JSONObject jsonResponse = translate(values);
                    int index = 0;
                    for (int i = 0; i < translate.length; i++) {
                        if (i == fromIndex) continue;
                        final String string = ((JSONObject) ((JSONObject) (jsonResponse.getJSONArray("responseData").get(index++))).getJSONObject("responseData")).getString("translatedText");
                        updateOutput(i, string.replaceAll("&quot;", "\'"));
                    }
                    progressDialog.dismiss();
                } catch (UnsupportedEncodingException e) {
//                    Log.e("TranslateActivity", e.getLocalizedMessage());
                    errorMessage = getString(R.string.error_unsupportedencodingexception, e.getLocalizedMessage());
                } catch (URISyntaxException e) {
//                    Log.e("TranslateActivity", e.getLocalizedMessage());
                    errorMessage = getString(R.string.error_urisyntaxexception, e.getLocalizedMessage());
                } catch (IOException e) {
//                    Log.e("TranslateActivity", e.getLocalizedMessage());
                    errorMessage = getString(R.string.error_ioexception, e.getLocalizedMessage());
                } catch (JSONException e) {
//                    Log.e("TranslateActivity", e.getLocalizedMessage());
                    errorMessage = getString(R.string.error_jsonexception, e.getLocalizedMessage());
                }
                progressDialog.dismiss();
                if (errorMessage != null) {
                    final String ms = errorMessage;
                    mHandler.post(new Runnable() {
                        public void run() {
                            new AlertDialog.Builder(TranslateActivity.this)
                                    .setTitle(getResources().getString(R.string.error))
                                    .setMessage(ms)
                                    .setPositiveButton(getString(R.string.translation_button_ok), null).show();
                        }
                    });
                }
            }
        }

        private void updateOutput(int index, String value) {
            switch (index) {
                case 0:
                    ((EditText) findViewById(R.id.output_1)).setText(value);
                    break;
                case 1:
                    ((EditText) findViewById(R.id.output_2)).setText(value);
                    break;
                case 2:
                    ((EditText) findViewById(R.id.output_3)).setText(value);
                    break;
            }
        }

        public void onClick(View v) {

            if (input.getEditableText().toString().trim().length() == 0) {
                new AlertDialog.Builder(TranslateActivity.this)
                        .setTitle("").setMessage(getString(R.string.input_empty_message))
                        .setPositiveButton(getString(R.string.translation_button_ok), null).show();

                return;
            }

            ProgressDialog progressDialog = ProgressDialog.show(TranslateActivity.this, getResources().getString(R.string.translation_progress), "", true);
            new Thread(new TranslateRunnable(progressDialog)).start();

        }


    }

    @Override
    protected void onPause() {
        super.onPause();
        SharedPreferences.Editor ed = mPrefs.edit();
        ed.putString("language_1", translate[0]);
        ed.putString("language_2", translate[1]);
        ed.putString("language_3", translate[2]);
        ed.commit();

    }

    private void updateLanguageInputs() {
        for (int i = 0; i < translate.length; i++) {
            for (int j = 0; j < supportedLanguages.size(); j++) {
                if (supportedLanguages.get(j).getCountryCode().equalsIgnoreCase(translate[i])) {
                    RelativeLayout childTabViewAt = (RelativeLayout) (mTabHost.getTabWidget().getChildTabViewAt(i));
                    int childCount = childTabViewAt.getChildCount();
                    for (int childIndex = 0; childIndex < childCount; childIndex++) {
                        if (childTabViewAt.getChildAt(childIndex) instanceof TextView) {
                            ((TextView) childTabViewAt.getChildAt(childIndex)).setText(supportedLanguages.get(j).getLanguageName());
                        }
                        if (childTabViewAt.getChildAt(childIndex) instanceof ImageView) {
                            if (flags[j] != -1) {
                                ((ImageView) childTabViewAt.getChildAt(childIndex)).setVisibility(View.VISIBLE);
                                ((ImageView) childTabViewAt.getChildAt(childIndex)).setImageResource(flags[j]);

                            } else ((ImageView) childTabViewAt.getChildAt(childIndex)).setVisibility(View.GONE);
                        }
                    }
                }
            }
        }
        clearTranslations();

    }

    private JSONObject translate(Object[] params) throws IOException, URISyntaxException, JSONException {
        final String defaultCharset = Charset.defaultCharset().name();

        String translateUrl = MessageFormat.format(url, params);
        HttpGet httpGet = new HttpGet((new URL(translateUrl)).toURI());
        httpGet.getParams().setParameter("http.connection.timeout", 10000);
        httpGet.getParams().setParameter("http.socket.timeout", 10000);


        httpGet.setHeader(new BasicHeader("Accept-Charset", UTF_8));
        httpGet.setHeader(new BasicHeader("Accept", "text/html"));
        httpGet.setHeader(new BasicHeader("User-Agent", "Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522+ (KHTML, like Gecko) Safari/419.3"));
        httpGet.setHeader(new BasicHeader("Accept-Encoding", "gzip,deflated"));
        DefaultHttpClient client = new DefaultHttpClient();
        HttpResponse response = client.execute(httpGet, new BasicHttpContext());
        InputStream httpInputStream = response.getEntity().getContent();
        Header contentEncoding = response.getFirstHeader("Content-Encoding");
        if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
            httpInputStream = new GZIPInputStream(httpInputStream);
        }
        final Header contentType = response.getEntity().getContentType();
        String encoding = contentType == null ? ISO_8859_1 : contentType.getValue().contains("charset=") ?
                contentType.getValue().substring(contentType.getValue().indexOf("charset=") + "charset=".length()) : ISO_8859_1;
        BufferedReader reader = new BufferedReader(new InputStreamReader(httpInputStream, encoding));

        StringBuilder builder = new StringBuilder();
        String line = null;

        while ((line = reader.readLine()) != null) {
            builder.append(line);
        }
        reader.close();
        return new JSONObject(convertFromEncodingToEncoding(builder.toString(), encoding, defaultCharset));
    }

    private String convertFromEncodingToEncoding(String text, String fromEncoding, String toEncoding) throws UnsupportedEncodingException {
        if (fromEncoding.equalsIgnoreCase(toEncoding)) return text;
        return new String(text.getBytes(toEncoding), toEncoding);
    }

    /*
    * (non-Javadoc)
    *
    * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
    */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.translate_menu, menu);
        this.menu = menu;
        return true;
    }

    private void clearTranslations() {
        ((EditText) findViewById(R.id.input_1)).setText("");
        ((EditText) findViewById(R.id.output_1)).setText("");
        ((EditText) findViewById(R.id.input_2)).setText("");
        ((EditText) findViewById(R.id.output_2)).setText("");
        ((EditText) findViewById(R.id.input_3)).setText("");
        ((EditText) findViewById(R.id.output_3)).setText("");
    }

    /*
    * (non-Javadoc)
    *
    * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
    */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch ((int) item.getItemId()) {
            case R.id.clear:
                clearTranslations();
                return true;
            case R.id.exit:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void loadLanguages(String[] languages, String[] codes) {
        for (int i = 0; i < languages.length; i++) {
            supportedLanguages.add(new Language(languages[i], codes[i]));
        }
    }

    private class Language {
        private String languageName;
        private String countryCode;

        private Language(String languageName, String countryCode) {
            this.languageName = languageName;
            this.countryCode = countryCode;
        }

        public String getLanguageName() {
            return languageName;
        }

        public String getCountryCode() {
            return countryCode;
        }

        @Override
        public String toString() {
            return languageName;
        }
    }
}